<TeXmacs|2.1>

<project|scheme-gnunet.tm>

<style|tmmanual>

<\body>
  Scheme-GNUnet uses <code*|guile-fibers> for concurrency, but supports
  POSIX-style threading as well, using the <code*|(ice-9 threads)> Guile
  module. More concretely, this means <code*|spawn-fiber> is used by default
  for starting asynchronuous computations and public procedures accept an
  optional <scm|#:spawn> argument accepting a procedure like
  <code*|spawn-fiber> or <code*|call-with-new-thread>.
  \<#2018\>Conditions\<#2019\> can be used for synchronising concurrent
  computations, see the documentation of <code*|guile-fibers> for details.

  <paragraph|Repeated conditions>Scheme-GNUnet has a variant of fibers
  conditions, named \<#2018\>repeated conditions\<#2019\>, in the module
  <scm|(gnu gnunet concurrency repeated-condition)>.<space|1em>It is
  unfortunately ill-documented.

  <section|Waiting for unreachability of objects>

  A service module often allows starting a few operations and
  cancelling/stopping them, freeing resources (ports, network, memory, CPU
  <text-dots>) used by the operation. It can be useful to also
  <em|automatically> cancel the operation when it becomes unreachable, for
  example in case an exception was raised before the code for cancelling the
  operation.

  To automatically cancel when the GC discovers the operation object to be
  lost, the records and procedures from <scm|(gnu gnunet concurrency
  lost-and-found)><index|(gnu gnunet concurrency lost-and-found)> can be
  used. But first, some terminology.

  <\description>
    <item*|lost>An object is <dfn|lost><index|lost> when it is, in GC terms,
    unreachable.

    <item*|found>A previously lost object is said to be
    <dfn|found><index|found> once this module discovers it was lost \V
    currently, this does not happen directly after it became unreachable,
    this module only discovers lost objects after a GC cycle (see
    <scm|after-gc-hook> in (guile)GC Hooks).

    By finding an object, it becomes reachable again and can therefore become
    lost again. However, it will only be found the first time it became lost.

    <item*|lost-and-found>Each found object is put inside their corresponding
    <dfn|lost-and-found><index|lost-and-found>, if any.
  </description>

  <\explain>
    <scm|(make-lost-and-found)>
  </explain|Make a fresh lost-and-found. It can be tested if an object is a
  lost-and-found with the predicate <scm|lost-and-found?>.>

  <\explain>
    <scm|(collect-lost-and-found-operation <var|lost-and-found>)>
  <|explain>
    Make a Fibers operation that waits until some objects have become found
    in <var|lost-and-found> and returns these objects as a list. In a few
    race circumstances, this operation can spuriously return the empty list.

    In the current implementation, this operation can not meaningfully be
    reused; in some circumstances, performing the returned operation again
    (with Fibers' <scm|perform-operation>) after it has previously been
    performed can cause the empty list to be returned even if new objects
    have been lost, without blocking.

    Summarised, don't reuse <scm|collect-lost-and-found-operation>s that have
    returned, always make a fresh one!
  </explain>

  <\explain>
    <scm|\<less\>losable\<gtr\>><index|\<less\>losable\<gtr\>>
  <|explain>
    This record type is the supertype of all objects that can be added to a
    lost-and-found. By constructing an object of this type, the object is
    automatically added to the lost-and-found that was passed to the
    constructor. Alternatively, falsehood can be passed to the constructor if
    the object should <em|not> be added to a lost-and-found.

    Due to unknown reasons<\footnote>
      perhaps a bug in Guile's implementation of RnRS records, or maybe not
    </footnote>, subtypes must define the \<#2018\>protocol\<#2019\> (see
    (guile)R6RS Records), otherwise the object will not be added to the
    lost-and-found.
  </explain>

  <\example>
    The following code constructs a lost-and-found and a few losable objects
    and it let the losable objects become lost, after which they are
    collected.

    <\scm-code>
      (import (gnu gnunet concurrency lost-and-found)

      \ \ \ \ \ \ \ \ (rnrs records syntactic) (fibers operations))

      (define lost-and-found (make-lost-and-found))

      (define-record-type (\<less\>foobar\<gtr\> make-foobar foobar?) (parent
      \<less\>losable\<gtr\>)

      \ \ (fields (immutable foo foobar-foo) (immutable bar foobar-bar))

      \ \ (protocol (lambda (%make)

      \ \ \ \ \ \ \ \ \ \ \ \ \ \ (lambda (foo bar) ((%make lost-and-found)
      foo bar)))))

      (begin

      \ \ (make-foobar 'foo 'bar) (make-foobar #\\x #\\y) (gc))

      (for-each (lambda (x) (pk 'found (foobar-foo x) (foobar-bar x)))

      \ \ \ \ \ \ \ \ \ \ (perform-operation

      \ \ \ \ \ \ \ \ \ \ \ (collect-lost-and-found-operation
      lost-and-found)))
    </scm-code>

    Output:

    <\verbatim-code>
      ;;; (found foo bar)

      ;;; (foo #\\x #\\y)
    </verbatim-code>
  </example>
</body>

<\initial>
  <\collection>
    <associate|page-medium|paper>
    <associate|save-aux|false>
  </collection>
</initial>